#include <queue>
#include <pthread.h>

using namespace std;

template<class T>
class blockQueue
{
public:
    blockQueue(int max)
        :_producer_cond(PTHREAD_COND_INITIALIZER),
        _consumer_cond(PTHREAD_COND_INITIALIZER),
        _lock(PTHREAD_MUTEX_INITIALIZER),
        _max(max)
    { }

    void push(const T& good)
    {
        pthread_mutex_lock(&_lock);
        if(_qu.size() > _max) {
            pthread_cond_signal(&_consumer_cond);
            pthread_cond_wait(&_producer_cond, &_lock);
        }
        _qu.push(good);
        pthread_mutex_unlock(&_lock);
    }

    T pop()
    {
        pthread_mutex_lock(&_lock);
        if(_qu.size() == 0) {
            pthread_cond_signal(&_producer_cond);
            pthread_cond_wait(&_consumer_cond, &_lock);
        }
        T good = _qu.front();
        _qu.pop();
        pthread_mutex_unlock(&_lock);
        return good;
    }

    ~blockQueue()
    {
        pthread_cond_destroy(&_producer_cond);
        pthread_cond_destroy(&_consumer_cond);
        pthread_mutex_destroy(&_lock);
    }

private:
    queue<T> _qu;
    pthread_cond_t _producer_cond;
    pthread_cond_t _consumer_cond;
    pthread_mutex_t _lock;
    int _max;
};
